[#assign title]聊天室[/#assign]
[#include "/common/_layout.html"/]
[#macro style]
<style>
    body {
        padding-top: 0px;
    }

    .container-fluid {
        padding: 0px;
    }

    .mint-navbar .mint-tab-item {
        padding: 10px 0px;
    }

    /** 气泡 */
    .bubble {
        position: relative;
        padding: 10px;
        margin: 0 52px 0 10px;
        line-height: 1.2;
        text-align: left;
        display: inline-block;
        -moz-border-radius: 10px;
        -webkit-border-radius: 10px;
        border-radius: 10px;
        background-color: #eee;
    }

    .bubble:after {
        content: "\00a0";
        width: 10px;
        height: 15px;
        position: absolute;
        display: block;
        top: 0;
        right: 100%;
        border: 0 solid transparent;
        border-bottom: 5px solid #eee;
        border-radius: 0 0 0 20px;
    }

    .bubble-right {
        margin: 0 10px 0 52px;
    }

    .bubble-right:after {
        top: 0;
        left: 100%;
        border-radius: 0 0 20px 0;
    }

    .chat-panel, .order-panel {
        margin-top: 3px;
    }

    /** 聊天人员列表 */
    .chat-panel .chat-player {
        margin: 0px;
        padding-top: 5px;
        text-align: center;
        border-bottom: 1px solid #ccc;
        width: 100%;
        display: table;
        content: " "
    }

    .chat-panel .chat-player .chat-player-head {
        width: 20%;
        float: left;
    }

    /** 昵称溢出显示省略号 */
    .chat-panel .chat-player .chat-player-head p {
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    .chat-panel .chat-player .chat-player-head img {
        width: 32px;
        height: 32px;
    }

    .chat-panel .chat-player p {
        margin: 0px;
        font-size: 12px;
    }

    .chat-panel .chat-body h6 {
        padding: 0 10px 0;
    }

    /** 聊天信息内容图片 */
    .chat-panel .chat-body img.chat-message-img {
        width: auto;
        height: auto;
        max-width: 100%;
        max-height: 100%;
    }

    /** 聊天信息发送面板 */
    .chat-panel .chat-bar {
        margin-bottom: 55px;
    }

    /** 信息输入框 */
    .chat-panel .chat-bar .input-group .form-control:focus {
        box-shadow: none;
    }

    /** 信息发送按钮 */
    .chat-panel .chat-bar .input-group img {
        width: 32px;
        height: 32px;
    }

    /** 信息发送按钮 */
    .chat-panel .chat-bar .input-group .btn {
        border: 1px solid #ced4da;
        background-color: inherit;
    }

    /** 聊天信息扩展功能面板 */
    .chat-panel .chat-bar .chat-popup {
        width: 100%;
        bottom: 56px;
        text-align: center;
    }

    /** 聊天信息扩展功能面板缩略图 */
    .chat-panel .chat-bar .chat-popup .img-thumbnail {
        margin-top: 10px;
        margin-bottom: 5px;
    }

    /** 聊天信息扩展功能面板缩略图文字 */
    .chat-panel .chat-bar .chat-popup p {
        margin: 0px;
    }
</style>
[/#macro]
[#macro body]
<mt-navbar v-model="selected">
    <mt-tab-item id="PLAYING">进行中</mt-tab-item>
    <mt-tab-item id="END">全部</mt-tab-item>
</mt-navbar>

<mt-tab-container v-model="selected">
    <mt-tab-container-item id="PLAYING" class="chat-panel">
        <mt-cell v-if="isNoParticipationGame" class="text-center" title="当前未报名游戏"></mt-cell>
        <template v-else>
            <div class="chat-player">
                <div class="chat-player-head" v-for="player in gamePlayers" @click="atUser(player)">
                    <img :src="player.head | headImg" class="rounded-circle" :alt="player.nickname"/>
                    <p :class="[player.id == customer.id ? 'text-primary' : 'text-secondary']">{{player.nickname}}</p>
                </div>
            </div>
            <div class="chat-body pre-scrollable"
                 :style="{'max-height': chatRecordHeight}">
                <ul class="list-unstyled">
                    <template v-for="chatRecord in chatRecordList">
                    [#-- 其他玩家消息 --]
                        <li class="media border-0 pt-3" v-if="chatRecord.customerId != customer.id">
                            <img class="align-self-start rounded-circle" :src="chatRecord.head | headImg"/>
                            <div class="media-body">
                                <h6 class="text-secondary">{{chatRecord.nickname}}</h6>
                                <chat-content class="chat-message bubble"
                                              :record="chatRecord" :msg-type="templateMsg"
                                              :room-sn="room.sn" :room-url="room.url"></chat-content>
                            </div>
                        </li>
                    [#-- 我的消息 --]
                        <li class="media border-0 pt-3" v-else>
                            <div class="media-body text-right">
                                <h6 class="text-secondary">{{chatRecord.nickname}}</h6>
                                <chat-content class="chat-message bubble bubble-right"
                                              :record="chatRecord" :msg-type="templateMsg"
                                              :room-sn="room.sn" :room-url="room.url"></chat-content>
                            </div>
                            <img class="align-self-start rounded-circle" :src="chatRecord.head | headImg"/>
                        </li>
                    </template>
                </ul>
            </div>
            <div class="chat-bar fixed-bottom">
                <div class="input-group">
                    <input type="text" autofocus class="form-control" placeholder="请输入信息内容"
                           v-model="sendChatRecord.content"/>
                    <div class="input-group-append">
                    [#-- 发送信息按钮 --]
                        <button type="button" class="btn rounded-right"
                                v-show="sendChatRecord.content"
                                @click="sendMessage">
                            <img src="/static/images/chat/send.svg"/>
                        </button>
                    [#-- 加号,展开更多功能 --]
                        <button type="button" class="btn rounded-right" v-show="!sendChatRecord.content"
                                @click="moreThanPopupVisible=true">
                            <img src="/static/images/chat/more.svg"/>
                        </button>
                    </div>
                </div>
                <mt-popup class="chat-popup"
                          v-model="moreThanPopupVisible"
                          position="bottom"
                          @click.native="moreThanPopupVisible = false">
                    <div class="row m-0">
                        <div class="col-3">
                            <img class="img-thumbnail" src="/static/images/chat/qrcode.svg"
                                 @click="sendMoreThanMessage('qrCode')"/>
                            <p>收款码</p>
                        </div>
                        <div class="col-3">
                            <img class="img-thumbnail" src="/static/images/chat/receipt.svg"
                                 @click="sendMoreThanMessage('end')"/>
                            <p>结束</p>
                        </div>
                        <div class="col-3">
                            <img class="img-thumbnail" src="/static/images/chat/house.svg"
                                 @click="sendMoreThanMessage('roomSn')"/>
                            <p>房号</p>
                        </div>
                    </div>
                </mt-popup>
            </div>
        </template>
    </mt-tab-container-item>
    <mt-tab-container-item id="END" class="order-panel pre-scrollable"
                           :style="{'max-height': orderGameHeight}">
        <mt-loadmore :top-method="refresh" ref="loadmore"
                     infinite-scroll-disabled="allLoaded" v-infinite-scroll="loadMore" infinite-scroll-distance="30">
            <mt-cell v-for="order in orderGameList">
                <template slot="title">
                    <span class="mint-cell-text">{{order.memo}}</span>
                    <span class="mint-cell-label">{{order.createdDate | formatDate}}</span>
                </template>
                <span :class="[order.status == 'COMPLETED' ? 'text-success' : 'text-danger']">{{order.status | orderStatusFilter}}</span>
            </mt-cell>
        </mt-loadmore>
        <div class="page-infinite-loading d-flex justify-content-center">
            <span v-show="allLoaded">没有更多了</span>
            <div v-show="!allLoaded">
                <div class="d-flex align-items-center">
                    <mt-spinner type="fading-circle" class="mr-2"></mt-spinner>
                    加载中...
                </div>
            </div>
        </div>
    </mt-tab-container-item>
</mt-tab-container>
[/#macro]
[#macro script]
<script type="text/x-template" id="chatContentTemplate">
    <div>
        <template v-if="record.content == msgType.qrCode">
            <div class="text-danger">
                请确认二维码是否属于赢家本人，
                <br/>输入金额时须核对收款人昵称等，
                <br/>转账前双方都未发现问题并导致转自出错，
                <br/>经客服确认后，双方各承担一半责任
            </div>
            <img class="chat-message-img" @load="calcScrollHeight"
                 :src="'/customer/qrcode/download/' + record.customerId"/>
        </template>
        <template v-else-if="record.content == msgType.roomSn">
            <a :href="roomUrl || 'javascript:;'">点击进入游戏</a>
            或进入游戏输入房号【{{roomSn}}】
        </template>
        <template v-else-if="record.content == msgType.end">
            [{{record.nickname}}]已申请结束游戏
            <br/>若无异议，请点击【<i class="iconfont icon-more"></i>】，然后点击【<i class="iconfont icon-receipt"></i>】
        </template>
        <template v-else>{{record.content}}</template>
    </div>
</script>
<script>
    var ChatContent = {
        props: {
            'record': {type: Object},
            'msgType': {type: Object},
            'roomSn': {type: String},
            'roomUrl': {type: String}
        },
        template: '#chatContentTemplate',
        methods: {
            calcScrollHeight: function () {
                app.calcChatScrollHeight()
            }
        }
    };
    var app = new Vue({
        el: '#app',
        components: {
            'chat-content': ChatContent
        },
        data: {
            selected: 'PLAYING',
            socket: null,
            customer: {},
            room: {},
            gamePlayers: [],
            chatRecordList: [],
            chatRecordHeight: '0px',
            sendChatRecord: {
                content: ''
            },
            moreThanPopupVisible: false,
            templateMsg: {
                roomSn: '[房号]',
                qrCode: '[收款二维码]',
                end: '[结束]',
            },
            /** 已结束游戏 */
            page: 0,
            allLoaded: false,
            orderGameList: [],
            orderStatusMapping: {},
            orderGameHeight: '0px'
        },
        methods: {
            /** 计算聊天记录面板高度 */
            calcChatRecordHeight: function () {
                var vm = this;
                vm.$nextTick(function () {
                    vm.chatRecordHeight = vm.calcScrollHeight('.chat-panel>.pre-scrollable') + 'px';
                });
            },
            /** 计算游戏记录面板高度 */
            calcOrderGameHeight: function () {
                var vm = this;
                vm.$nextTick(function () {
                    vm.orderGameHeight = vm.calcScrollHeight('.order-panel.pre-scrollable') + 'px';
                });
            },
            /** 计算聊天面板滚动条高度 */
            calcChatScrollHeight: function () {
                var vm = this;
                vm.$nextTick(function () {
                    var container = document.querySelector('.chat-panel>.chat-body');
                    container.scrollTop = container.scrollHeight;
                })
            },
            /** 以WebSocket方式发起链接 */
            connectWebSocket: function () {
                var vm = this;
                if (typeof(WebSocket) == "undefined") {
                    return vm.$toast('您使用的浏览器版本过低,请升级浏览器');
                }
                if (vm.isNoParticipationGame) {
                    return;
                }

                var setTimeoutResult = undefined;
                var closeFunction = function (event) {
                    setTimeoutResult = setTimeout(vm.connectWebSocket, 1000 * 10)
                };

                var errorFunction = function (event) {
                    axios.post('/customer/detail').catch(function (error) {
                        if (setTimeoutResult) {
                            clearTimeout(setTimeoutResult);
                        }
                    });
                };

                var socket = vm.socket;
                /**
                 只读属性 readyState 表示连接状态，可以是以下值：
                 常量        值  描述
                 CONNECTING  0   连接还没开启。
                 OPEN        1   连接已开启并准备好进行通信。
                 CLOSING     2   连接正在关闭的过程中。
                 CLOSED      3   连接已经关闭，或者连接无法建立。
                 */
                if (socket && socket.readyState < WebSocket.CLOSING) {
                    return;
                }
                // Create WebSocket connection.
                var protocol = window.location.protocol.replace(/http/, 'ws');
                socket = new WebSocket(protocol + '//' + window.location.host + '/WebSocket/chat/' + vm.room.id);
                vm.socket = socket;
                // Connection closed
                socket.addEventListener('close', closeFunction);
                // Connection error
                socket.addEventListener('error', errorFunction);
                // Listen for messages
                socket.addEventListener('message', function (event) {
                    var data = event.data;
                    data = JSON.parse(data);
                    if (!data.success) {
                        return vm.$toast(data.message || '信息发送失败');
                    }
                    if (data.code == 1) {
                        vm.chatRecordList = data.data;
                    } else if (data.code == 2) {
                        setTimeout(vm.refreshRoom, 1000);
                        if (data.data) {
                            vm.chatRecordList.push(data.data);
                        }
                    } else if (data.code == 99) {
                        vm.$messagebox({
                            title: '游戏已结束',
                            message: '您可以在[游戏大厅]报名其它游戏',
                            confirmButtonText: '前往游戏大厅',
                            closeOnClickModal: false
                        }).then(function (value) {
                            // if ('confirm' == value) {
                            window.location.href = '/';
                            // }
                        });
                    } else {
                        vm.chatRecordList.push(data.data);
                    }
                });
            },
            /** 发送信息 */
            sendMessage: function (event, message) {
                var vm = this;
                message = message || vm.sendChatRecord;
                if (!message.content) {
                    return false;
                }
                var stringify = JSON.stringify(message);
                message.content = '';
                /**
                 只读属性 readyState 表示连接状态，可以是以下值：
                 常量        值  描述
                 CONNECTING  0   连接还没开启。
                 OPEN        1   连接已开启并准备好进行通信。
                 CLOSING     2   连接正在关闭的过程中。
                 CLOSED      3   连接已经关闭，或者连接无法建立。
                 */
                if (vm.socket.readyState > WebSocket.OPEN) {
                    vm.connectWebSocket();
                    var index = 10;
                    var handler = function () {
                        if (index <= 0) {
                            return;
                        }
                        index--;
                        if (vm.socket.readyState == WebSocket.OPEN) {
                            vm.socket.send(stringify);
                        } else {
                            setTimeout(handler, 300);
                        }
                    };
                    setTimeout(handler, 300);
                    return false;
                }
                vm.socket.send(stringify);
                return false;
            },
            /** 发送@信息 */
            atUser: function (customer) {
                this.sendChatRecord.content += "@" + customer.nickname;
            },
            /**
             * 发送功能信息
             * type: 功能类别
             */
            sendMoreThanMessage: function (type) {
                var vm = this;
                if (type == 'roomSn' && !vm.room.sn) {
                    return vm.$toast("房号正在分配中，若长时间未发放房号，请联系客服");
                }
                var message = {
                    content: vm.templateMsg[type]
                };
                vm.sendMessage(null, message);
                return false;
            },
            /** 刷新房间信息 */
            refreshRoom: function () {
                var vm = this;
                axios.post('/room/detail').then(function (response) {
                    if (!response.data) {
                        return;
                    }
                    vm.room = response.data;
                    var title = [];
                    title.push('[第');
                    title.push(vm.room.period);
                    title.push('期]');
                    title.push(vm.room.name);
                    title.push('【');
                    title.push(vm.room.region);
                    title.push('】');
                    document.title = title.join('');
                    axios.post('/room/players/' + vm.room.id).then(function (response) {
                        vm.gamePlayers = response.data;
                        vm.calcChatRecordHeight();
                    });
                    vm.connectWebSocket();
                });
            },
            /** 刷新游戏订单 */
            refresh: function () {
                var vm = this;
                vm.page = 1;
                vm.allLoaded = false;
                axios.post('/order/game/list', {page: vm.page}).then(function (response) {
                    vm.orderGameList = response.data;
                    vm.$refs.loadmore.onTopLoaded();
                }).catch(function (err) {
                    vm.$refs.loadmore.onTopLoaded();
                });
            },
            /** 加载更多游戏订单 */
            loadMore: function () {
                var vm = this;
                vm.page++;
                axios.post('/order/game/list', {page: vm.page}).then(function (response) {
                    var data = response.data;
                    vm.orderGameList = vm.orderGameList.concat(data);
                    if (data.length < 10) {
                        vm.allLoaded = true;
                    }
                    // vm.$refs.loadmore.onBottomLoaded();
                }).catch(function (err) {
                    // vm.$refs.loadmore.onBottomLoaded();
                });
            }
        },
        computed: {
            /** 是否未参加游戏 */
            isNoParticipationGame: function () {
                return !this.room || !this.room.id;
            }
        },
        filters: {
            orderStatusFilter: function (status) {
                return app.orderStatusMapping[status];
            }
        },
        watch: {
            /** 监视聊天记录变化,并滚动至最新消息 */
            chatRecordList: function (value) {
                this.calcChatScrollHeight()
            },
            /** 监听面板变化,并重新计算游戏订单高度 */
            selected: function (value) {
                if (value != 'END') {
                    return;
                }
                var vm = this;
                vm.$nextTick(function () {
                    vm.calcOrderGameHeight();
                })
            }
        },
        mounted: function () {
            appHeader.isShow = false;
            appFooter.isShow = true;
            var vm = this;
            vm.refreshRoom();
            axios.post('/customer/detail').then(function (response) {
                vm.customer = response.data;
            });
            axios.post('/order/game/status').then(function (response) {
                vm.orderStatusMapping = response.data;
            });
        }
    });
</script>
[/#macro]